<template>
	<label :class="wrapClasses">
		<span :class="checkboxClasses">
			<span :class="innerClasses"></span>
			<input
				v-if="group"
				type="checkbox"
				:class="inputClasses"
				:disabled="disabled"
				:value="label"
				v-model="model"
				:name="name"
				@change="change"
				@focus="onFocus"
				@blur="onBlur"
			/>
			<input
				v-else
				type="checkbox"
				:class="inputClasses"
				:disabled="disabled"
				:checked="currentValue"
				:name="name"
				@change="change"
				@focus="onFocus"
				@blur="onBlur"
			/>
		</span>
		<slot>
			<span v-if="showSlot">{{ label }}</span>
		</slot>
	</label>
</template>
<script lang="ts">
	import Anes from "../base";
	import { Prop, Emit, Component, Watch, Mixins } from "vue-property-decorator";
	//	import { FormItem } from "../form";
	import { findComponentsUpward } from "../../utils/assist";
	import CheckboxGroup from "./checkbox-group.vue";

	const prefixCls = "ivu-checkbox";
	@Component
	export default class Checkbox extends Mixins(Anes) {
		@Prop({ type: Boolean, default: false }) disabled!: boolean;
		@Prop({ type: [String, Number, Boolean], default: false }) value!:
			| string
			| number
			| boolean;

		@Prop({ type: [String, Number, Boolean], default: true }) trueValue!:
			| string
			| number
			| boolean;
		@Prop({ type: [String, Number, Boolean], default: false }) falseValue!:
			| string
			| number
			| boolean;
		@Prop({ type: [String, Number, Boolean], default: false }) label!:
			| string
			| number
			| boolean;
		@Prop({ type: Boolean, default: false }) indeterminate!: boolean;
		@Prop({ type: Boolean, default: false }) border!: boolean;
		@Prop() name!: string;

		model = new Array<string | number | boolean>();
		currentValue = this.value;
		group = false;
		showSlot = true;
		parent = new CheckboxGroup();
		focusInner = false;

		get wrapClasses() {
			return [
				`${prefixCls}-wrapper`,
				{
					[`${prefixCls}-group-item`]: this.group,
					[`${prefixCls}-wrapper-checked`]: this.currentValue,
					[`${prefixCls}-wrapper-disabled`]: this.disabled,
					[`${prefixCls}-${this.size}`]: !!this.size,
					[`${prefixCls}-border`]: this.border
				}
			];
		}
		get checkboxClasses() {
			return [
				`${prefixCls}`,
				{
					[`${prefixCls}-checked`]: this.currentValue,
					[`${prefixCls}-disabled`]: this.disabled,
					[`${prefixCls}-indeterminate`]: this.indeterminate
				}
			];
		}
		get innerClasses() {
			return [
				`${prefixCls}-inner`,
				{
					[`${prefixCls}-focus`]: this.focusInner
				}
			];
		}
		get inputClasses() {
			return `${prefixCls}-input`;
		}
		updateModel() {
			this.currentValue = this.value === this.trueValue;
		}

		mounted() {
			const parents = findComponentsUpward<CheckboxGroup>(this, "CheckboxGroup");

			if (parents.length > 0) {
				this.group = true;
				this.parent = parents[0];
			}

			if (this.group) {
				this.parent.updateModel(true);
			} else {
				this.updateModel();
				this.showSlot = this.$slots.default !== undefined;
			}
		}
		@Emit()
		change(event: Event) {
			if (this.disabled) {
				return false;
			}

			const checked = (event.target as HTMLInputElement).checked;
			this.currentValue = checked;

			const value = checked ? this.trueValue : this.falseValue;
			this.$emit("input", value);

			if (this.group) {
				this.parent.change(this.model);
			} else {
				this.$emit("on-change", value);
				//	this.dispatch<FormItem>("on-form-change", value);
			}
		}
		@Emit()
		onBlur() {
			this.focusInner = false;
		}
		@Emit()
		onFocus() {
			this.focusInner = true;
		}
		@Watch("value")
		onChangeValue(
			newVal: string | number | boolean,
			oldVal: string | number | boolean
		) {
			if (newVal === this.trueValue || newVal === this.falseValue) {
				this.updateModel();
			} else {
				throw "Value should be trueValue or falseValue.";
			}
		}
	}
</script>
